/*
 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"

#define SYS_DELAY_TICKS 200
#define TASK_STACK_SIZE 4096
#define TASK_PRIO 25

#define DEFAULT_VREF 3300 // 默认参考电压，单位mV
static esp_adc_cal_characteristics_t *adc_chars;

#define myADC_heat_sensitive_channel ADC_CHANNEL_9      // 通道9 酒精传感器Ao输出
#define AD_Value1_Channnel myADC_heat_sensitive_channel // 重新定义一个, 为例后续更好的更改

#define width ADC_WIDTH_BIT_12 // ADC分辨率 12位
#define atten ADC_ATTEN_DB_11  // ADC衰减   11 dB 衰减，输入电压范围为 0-3.3V。
#define unit ADC_UNIT_2        // ADC2
#define NO_OF_SAMPLES 128      // 采样次数, 目的: 多次采样, 滤波

/**
 * @description: ADC初始化
 * @return {无}
 */
void myADC_Init()
{
    adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); // 分配内存
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP)
    {
        printf("eFuse Two Point: %d\n", val_type);
    }
    else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF)
    {
        printf("eFuse Vref: %d\n", val_type);
    }
    else
    {
        printf("Default Vref: %d\n", val_type);
    }

    // 配置ADC2通道
    adc2_config_channel_atten((adc2_channel_t)AD_Value1_Channnel, atten);
}

/**
 * @description: 获取传感器的AD值和电压值
 * @param {int16_t} *AD_Value1 第一个传感器的AD值的地址
 * @param {float*} Voltage1    第一个传感器的电压值的地址
 * @return {*}
 */
void myADC_GetAdAndVoltage_Value(int16_t *AD_Value1, float *Voltage1)
{
    uint32_t adc_reading1 = 0;
    for (int i = 0; i < NO_OF_SAMPLES; i++)
    { // 多次采样, 滤波
        int raw;
        if (adc2_get_raw((adc2_channel_t)AD_Value1_Channnel, width, &raw) == ESP_OK)
        {
            adc_reading1 += raw; // 采集电压值
        }
    }
    adc_reading1 /= NO_OF_SAMPLES; // 得到滤波后的数据

    // esp_adc_cal_raw_to_voltage返回的是mV, 想得到单位V, 除以1000
    *AD_Value1 = (int16_t)adc_reading1;                                       // 转换为int16_t类型
    *Voltage1 = esp_adc_cal_raw_to_voltage(adc_reading1, adc_chars) / 1000.0; // 获取电压值
}

int16_t light_AdVal;
float light_Voltage;

static void gpio_test(void)
{
    myADC_Init();

    while (1)
    {
        myADC_GetAdAndVoltage_Value(&light_AdVal, &light_Voltage);
        printf("gz adc cal: %d\t gz v: %.2f \n", light_AdVal, light_Voltage);

        sleep(2); // 延时
    }
}

static void gpio_example_task(void)
{
    osThreadAttr_t attr;
    int g_taskID;

    attr.name = "adc_test";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = TASK_STACK_SIZE;
    attr.priority = TASK_PRIO;
    g_taskID = osThreadNew((osThreadFunc_t)gpio_test, NULL, &attr);
    if (g_taskID == NULL)
    {
        printf("Failed to create Test GPIO thread!\n");
    }
}

OHOS_APP_RUN(gpio_example_task);